package com.someclip.component.core
{
	import authoring.authObject;
	import com.someclip.component.interfaces.IComponent;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.utils.getDefinitionByName;
	import flash.utils.getTimer;

	public class Component extends SomeSprite
	{
		private var _id:String;
		private var _resizeWithParent:Number = -1;
		private var _fillColor:int=-1;
		private var _oldFillColor:int=-1;
		//style property
		private var _styleLink:Object;
		private var _oldStyleLink:Object;
		private var _styleInstance:DisplayObject;
		//layout property
		private var _top:Number;
		private var _oldTop:Number;
		private var _bottom:Number;
		private var _oldBottom:Number;
		private var _vCenter:Number;
		private var _oldVCenter:Number;
		
		private var _left:Number;
		private var _oldLeft:Number;
		private var _right:Number;
		private var _oldRight:Number;
		private var _hCenter:Number;
		private var _oldHCenter:Number;
		
		private var _parentW:Number;
		private var _oldParentW:Number;
		private var _parentH:Number;
		private var _oldParentH:Number;
		
		private var _setW:Number;
		private var _currentW:Number;
		private var _oldSetW:Number;
		private var _setH:Number;
		private var _currentH:Number;
		private var _oldSetH:Number;
		
		
		public function get id():String 
		{
			return _id;
		}
		
		public function set id(value:String):void 
		{
			_id = value;
		}
		/**
		 * 设置组件自身跟随父容器的大小改变而改变的百分比(0-1),-1表示不跟随父容器改变大小;
		 */
		public function get resizeWithParent():Number 
		{
			return _resizeWithParent;
		}
		
		public function set resizeWithParent(value:Number):void 
		{
			_resizeWithParent = value;
		}
		
		public function get fillColor():int
		{
			return _fillColor;
		}
		
		public function set fillColor(value:int):void
		{
			_fillColor = value;
			setInvalidate();
		}
		
		private function setInvalidate():void
		{
			if (stage)
			{
				stage.invalidate();
			}
		}
		
		//-----setup-----------------------------------------------------------------------------------------------//
		public function Component()
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE, handleThisAddedToStage);
		}
		
		protected function handleThisAddedToStage(event:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE, handleThisAddedToStage);
			this.addEventListener(Event.REMOVED_FROM_STAGE, handleThisRemovedFromStage);
			stage.addEventListener(Event.RENDER, handleStageRender);
			if (this.parent is Stage || !(this.parent is IComponent))
			{
				stage.addEventListener(Event.RESIZE, handleStageResize);
			}
			stage.invalidate();
		}

		protected function handleStageResize(event:Event):void
		{
			stage.invalidate();
		}

		protected function handleThisRemovedFromStage(event:Event):void
		{
			this.removeEventListener(Event.REMOVED_FROM_STAGE, handleThisRemovedFromStage);
			stage.removeEventListener(Event.RENDER, handleStageRender);
			if (this.parent is Stage || !(this.parent is IComponent))
			{
				stage.removeEventListener(Event.RESIZE, handleStageResize);
			}
			this.addEventListener(Event.ADDED_TO_STAGE, handleThisAddedToStage);
		}

		protected function handleStageRender(event:Event):void
		{
			if (styleChange())
			{
				renderStyle();
			}
			if (layoutChange())
			{
				reLayout();
			}
			if (colorChange())
			{
				fillBg();
			}
		}
		
		private function fillBg():void 
		{
			this.graphics.clear();
			if (this.fillColor != -1)
			{
				this.graphics.beginFill(_fillColor, 1);
				this.graphics.drawRect(0, 0, this.width, this.height);
				this.graphics.endFill();
			}
		}
		
		private function colorChange():Boolean 
		{
			if (_oldFillColor != _fillColor)
			{
				_oldFillColor = _fillColor;
				return true;
			}
			return false;
		}
		//-------setup----------------------------------------------------------------------------------------//
		
		//---------layout--start--------------------------------------------------------------------------------//
		
		private function reLayout():void
		{
			var tx:Number = super.x;
			var ty:Number = super.y;
			if (!isNaN(_left))
			{
				tx = _left;
			}
			if (!isNaN(_right))
			{
				tx = _parentW - _setW - _right;
			}
			if (!isNaN(_hCenter))
			{
				tx = (_parentW / 2 - _setW / 2) + _hCenter;
			}
			if (!isNaN(_top))
			{
				ty = _top;
			}
			if (!isNaN(_bottom))
			{
				ty = _parentH - _setH - _bottom;
			}
			if (!isNaN(_vCenter))
			{
				ty = (_parentH / 2 - _setH / 2) + _vCenter;
			}
			super.x = tx;
			super.y = ty;
		
		}

		private function layoutChange():Boolean
		{
			var bol:Boolean = false;
			if (parentChange())
			{
				bol = true;
			}
			if (sizeChange())
			{
				bol = true;
			}
			if (boundChange())
			{
				bol = true;
			}
			return bol;
		}
		
		public function get top():Number 
		{
			return _top;
		}
		
		public function set top(value:Number):void 
		{
			_top = value;
			_bottom = NaN;
			_vCenter = NaN;
			setInvalidate();
		}
		
		public function get bottom():Number 
		{
			return _bottom;
		}
		
		public function set bottom(value:Number):void 
		{
			_bottom = value;
			_top = NaN;
			_vCenter = NaN;
			setInvalidate();
		}
		
		public function get vCenter():Number 
		{
			return _vCenter;
		}
		
		public function set vCenter(value:Number):void 
		{
			_vCenter = value;
			_top = NaN;
			_bottom = NaN;
			setInvalidate();
		}
		
		public function get left():Number 
		{
			return _left;
		}
		
		public function set left(value:Number):void 
		{
			_left = value;
			_right = NaN;
			_hCenter = NaN;
			setInvalidate();
		}
		
		public function get right():Number 
		{
			return _right;
		}
		
		public function set right(value:Number):void 
		{
			_right = value;
			_left = NaN;
			_hCenter = NaN;
			setInvalidate();
		}
		
		public function get hCenter():Number 
		{
			return _hCenter;
		}
		
		public function set hCenter(value:Number):void 
		{
			_hCenter = value;
			_left = NaN;
			_right = NaN;
			setInvalidate();
		}
		
		
		private function boundChange():Boolean 
		{
			var bol:Boolean = false;
			//top
			if (isNaN(_oldTop))
			{
				if (!isNaN(_top))
				{
					_oldTop = _top;
					bol = true;
				}
			}else
			{
				if (_oldTop != _top)
				{
					_oldTop = _top;
					bol = true;
				}
			}
			//bottom
			if (isNaN(_oldBottom))
			{
				if (!isNaN(_bottom))
				{
					_oldBottom = _bottom;
					bol = true;
				}
			}else
			{
				if (_oldBottom != _bottom)
				{
					_oldBottom = _bottom;
					bol = true;
				}
			}
			//vCenter
			if (isNaN(_oldVCenter))
			{
				if (!isNaN(_vCenter))
				{
					_oldVCenter = _vCenter;
					bol = true;
				}
			}else
			{
				if (_oldVCenter != _vCenter)
				{
					_oldVCenter = _vCenter;
					bol = true;
				}
			}
			//left
			if (isNaN(_oldLeft))
			{
				if (!isNaN(_left))
				{
					_oldLeft = _left;
					bol = true;
				}
			}else
			{
				if (_oldLeft != _left)
				{
					_oldLeft = _left;
					bol = true;
				}
			}
			//right
			if (isNaN(_oldRight))
			{
				if (!isNaN(_right))
				{
					_oldRight = _right;
					bol = true;
				}
			}else
			{
				if (_oldRight != _right)
				{
					_oldRight = _right;
					bol = true;
				}
			}
			//hCenter
			if (isNaN(_oldHCenter))
			{
				if (!isNaN(_hCenter))
				{
					_oldHCenter = _hCenter;
					bol = true;
				}
			}else
			{
				if (_oldHCenter != _hCenter)
				{
					_oldHCenter = _hCenter;
					bol = true;
				}
			}
			
			return bol;
			
		}
		
		override public function get x():Number
		{
			return super.x;
		}
		
		override public function set x(value:Number):void
		{
			_left = NaN;
			_right = NaN;
			_hCenter = NaN;
			super.x = value;
		}
		
		override public function get y():Number
		{
			return super.y;
		}
		
		override public function set y(value:Number):void
		{
			_top = NaN;
			_bottom = NaN;
			_vCenter = NaN;
			super.y = value;
		}
		
		override public function get width():Number
		{
			if(isNaN(_setW))
			{
				return 0;
			}
			return _setW;
		}
		
		override public function set width(value:Number):void
		{
			_setW = value;
			setInvalidate();
		}
		
		override public function get height():Number
		{
			if(isNaN(_setH))
			{
				return 0;
			}
			return _setH;
		}
		
		override public function set height(value:Number):void
		{
			_setH = value;
			setInvalidate();
		}
		
		private function sizeChange():Boolean 
		{
			var bol:Boolean = false;
			if (isNaN(_oldSetW))
			{
				if (!isNaN(_setW))
				{
					_oldSetW = _setW;
					bol = true;
				}
			}else
			{
				if (_oldSetW != _setW)
				{
					_oldSetW = _setW;
					bol = true;
				}
			}
			if (isNaN(_oldSetH))
			{
				if (!isNaN(_setH))
				{
					_oldSetH = _setH;
					bol = true;
				}
			}else
			{
				if (_oldSetH != _setH)
				{
					_oldSetH = _setH;
					bol = true;
				}
			}
			if (bol)
			{
				fillBg();
			}
			return bol;
		}
		
		private function caculateSize():void 
		{
			if (isNaN(_setW) && isNaN(_setH))
			{
				if (_styleInstance)
				{
					_setW = _styleInstance.width;
					_setH = _styleInstance.height;
				}
			}
			
		}
		
		private function parentChange():Boolean 
		{
			caculateParentSize();
			var bol:Boolean = false;
			if (isNaN(_oldParentW))
			{
				_oldParentW = _parentW;
				bol = true;
			}else
			{
				if (_oldParentW != _parentW)
				{
					_oldParentW = _parentW;
					bol = true;
				}
			}
			if (isNaN(_oldParentH))
			{
				_oldParentH = _parentH;
				bol = true;
			}else
			{
				if (_oldParentH != _parentH)
				{
					_oldParentH = _parentH;
					bol = true;
				}
			}
			if (_resizeWithParent != -1)
			{
				_setW = _parentW * _resizeWithParent;
				_setH = _parentH * _resizeWithParent;
			}
			return bol;
		}
		
		private function caculateParentSize():void
		{
			if (this.parent == null)
			{
				_parentW = 0;
				_parentH = 0;
			}else
			{
				if (this.parent is Stage)
				{
					_parentW = Stage(this.parent).stageWidth;
					_parentH = Stage(this.parent).stageHeight;
				}else
				{
					_parentW = this.parent.width;
					_parentH = this.parent.height;
				}
			}
		}
		
		//----layout--end-------------------------------------------------------------------------------------------------------//
		
		
		//-----style--start---------------------------------------------------------------------------------------------------//
		public function get styleLink():Object
		{
			return _styleLink;
		}

		public function set styleLink(value:Object):void
		{
			_styleLink = value;
			setInvalidate();
		}
		
		private function renderStyle():void
		{
			clearStyle();
			initStyle();
		}
		
		private function initStyle():void 
		{
			if (_styleLink is DisplayObject)
			{
				_styleInstance = _styleLink as DisplayObject;
				
			}
			if (_styleLink is String && _styleLink != "")
			{
				var tempCls:Class;
				try
				{
					tempCls = getDefinitionByName(String(_styleLink)) as Class;
				}catch (e:Error)
				{
					trace("StyleError:",e.message);
				}
				if (tempCls)
				{
					_styleInstance = new tempCls();
				}
			}
			if (_styleInstance && _styleInstance is DisplayObject)
			{
				if (_styleInstance is BitmapData)
				{
					_styleInstance = new Bitmap(_styleInstance as BitmapData);
				}
				if (_styleInstance is MovieClip)
				{
					MovieClip(_styleInstance).gotoAndStop(1);
				}
				this.addChildAt(_styleInstance, 0);
				if (isNaN(_setW) || isNaN(_setH))
				{
					this.width = _styleInstance.width;
					this.height = _styleInstance.height;
				}else
				{
					_styleInstance.width = this.width;
					_styleInstance.height = this.height;
				}
			}
		}
		
		private function clearStyle():void 
		{
			if (_styleInstance)
			{
				if (this.contains(_styleInstance))
				{
					this.removeChild(_styleInstance);
				}
				if (_styleInstance is Bitmap)
				{
					(_styleInstance as Bitmap).bitmapData.dispose();
				}
				_styleInstance = null;
			}
		}

		private function styleChange():Boolean
		{
			if(_styleLink==null && _oldStyleLink==null)
			{
				return false;
			}
			if (_oldStyleLink == null)
			{
				_oldStyleLink == _styleLink;
				return true;
			}
			if (_oldStyleLink == _styleLink)
			{
				return false;
			}
			_oldStyleLink = _styleLink;
			return true;
		}
		//--------style--end---------------------------------------------------------------------------------------------//
		
		override public function getChildAt(index:int):DisplayObject
		{
			if (_styleInstance && contains(_styleInstance))
			{
				return super.getChildAt(index + 1);
			}
			return super.getChildAt(index);
		}
		
		override public function get numChildren():int
		{
			if (_styleInstance && contains(_styleInstance))
			{
				return super.numChildren - 1;
			}
			return super.numChildren;
		}
	}
}
